﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace TestDataFileManipulator
{
    public partial class ConvertParametersForm : Form
    {
        public ConvertParametersForm()
        {
            InitializeComponent();
        }

        private void buttonBrowseSourceFile_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog ofd = new OpenFileDialog())
            {
                ofd.RestoreDirectory = true;
                if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    this.textBoxSourceFile.Text = ofd.FileName;
                    this.textBoxTargetFile.Text = ofd.FileName + ".conv.txt";
                }
            }
        }

        private void buttonConvert_Click(object sender, EventArgs e)
        {
            string[] sourceSeperators = this.multipleColumnSeparatorUserControlSource.GetSeparators();
            string targetSeparator = this.singleColumnSeparatorUserControlTarget.GetSeperator();

            if (sourceSeperators == null)
            {
                MessageBox.Show("No source separator(s) selected", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (targetSeparator == null)
            {
                MessageBox.Show("No target separator selected", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            try
            {
                this.Enabled = false;
                ConvertFile(this.textBoxSourceFile.Text, this.textBoxTargetFile.Text,
                    sourceSeperators, targetSeparator, this.checkBoxTranspose.Checked);
                MessageBox.Show("Done", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Failed:\n" + ex.ToString(), "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            finally
            {
                this.Enabled = true;
            }

        }

        private void ConvertFile(string sourceFile, string targetFile, string[] sourceSeperators, string targetSeparator, bool transposeData)
        {
            List<string[]> dataset = new List<string[]>();

            // Load data file to memory
            using (StreamReader sr = new StreamReader(sourceFile))
            {
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    string[] lineParts = line.Split(sourceSeperators, StringSplitOptions.None);
                    dataset.Add(lineParts);
                }
            }

            // Trim source end
            for (int row = dataset.Count - 1; row >= 0; row--)
            {
                if ((dataset[row].Length == 1) && (dataset[row][0].Trim() == ""))
                    dataset.RemoveAt(row);
                else
                    break;
            }

            List<string[]> output = ManipulateDataStructure(transposeData, dataset);

            // Save data file
            using (StreamWriter sw = new StreamWriter(targetFile))
            {
                for (int row = 0; row < output.Count; row++)
                {
                    string[] rowData = output[row];
                    StringBuilder sb = new StringBuilder();
                    for (int col = 0; col < rowData.Length; col++)
                    {
                        if (col > 0)
                            sb.Append(targetSeparator);
                        sb.Append(rowData[col]);
                    }

                    sw.WriteLine(sb.ToString());
                }
            }
        }

        private static List<string[]> ManipulateDataStructure(bool transposeData, List<string[]> dataset)
        {
            List<string[]> output;
            if ((transposeData == true) && (dataset.Count > 0))
            {
                int columnsCount = dataset[0].Length;

                // Check that the source data is rectangular
                for (int row = 1; row < dataset.Count; row++)
                    if (dataset[row].Length != columnsCount)
                        throw new Exception(string.Format("Number of item in row #{0} is {1} (other rows contain {2} items)", row, dataset[row].Length, columnsCount));

                // Perform transpose
                output = new List<string[]>();
                for (int col = 0; col < columnsCount; col++)
                {
                    string[] newRow = new string[dataset.Count];
                    for (int row = 0; row < dataset.Count; row++)
                        newRow[row] = dataset[row][col];
                    output.Add(newRow);
                }
            }
            else
                output = dataset;
            return output;
        }
    }
}
